/**
 * @fileOverview Active逻辑活动类源文件
 * @author <a href="http://sivory.my.phpcloud.com">sivory</a>
 * @version 0
 */

/**
 * @class Active逻辑活动类。
 * @param {Name.Sivory.Opensea.Game} host 当前逻辑活动类所从属的游戏实例
 *
 */
Name.Sivory.Opensea.Active = function(host, id) {
	this.$super = OS_Resource;
	if(this.$super(host, id) === false) return;
	delete this.$super;

	var instance = this;
	//脚本执行指针，指向当前正在运行的脚本地址，-1为不执行
	var actuatorPoint = -1;
	//脚本执行队列
	var actuators = null;

	//可见条件
	var enableCondition = null;

	//活动是否可见 不可见的活动不截获事件，不显示，不更新状态，不占用地图空间
	var enable = true;
	this.isEnable = function() {
		return enable;
	}

	//目前的脚本是否正在运行
	var running = false;
	this.isRunning = function() {
		return running;
	}
	//执行脚本
	this.run = function() {
		//不能执行一个已经在运行的脚本
		if(running) return;
		running = true;
		actuatorPoint = 0; //转向脚本入口
	}
	//终止脚本
	this.stop = function() {
		running = false;
		actuatorPoint = -1;
	}
	//跳转脚本
	this.goto = function(index) {
		if(!running) return;
		actuatorPoint = index;
	}

	//目前的脚本是否被阻塞（被阻塞也算是正在运行）
	var paused = false;

	//暂停脚本的执行
	this.pause = function() {
		paused = true;
	}
	//恢复脚本的执行
	this.resume = function() {
		paused = false;
	}

	//移动结束事件代理
	var moveHandler = {};

	//获得与触发器相应的事件处理函数
	var triggerToHandler = {};

	//将要注册在全局事件监听器中的托管，目的是监听对于本活动的confirm事件
	var confirmEventHandler = function(sender, params) {
			if(!instance.isEnable()) return false;
			//确定主角的位置与朝向，以判断是否在激发目前的活动
			var row_offset = 0;
			var col_offset = 0;
			if(sender.direction == 0) row_offset = -1;
			else if(sender.direction == 1) col_offset = 1;
			else if(sender.direction == 2) row_offset = 1;
			else if(sender.direction == 3) col_offset = -1;
			var check_col = Math.round(sender.currentPosition.x / host.config.squarewidth) + col_offset;
			var check_row = Math.round(sender.currentPosition.y / host.config.squareheight) + row_offset;

			var ins_ceil_col = Math.ceil(instance.currentPosition.x / host.config.squarewidth);
			var ins_flor_col = Math.floor(instance.currentPosition.x / host.config.squarewidth);
			var ins_ceil_row = Math.ceil(instance.currentPosition.y / host.config.squareheight);
			var ins_flor_row = Math.floor(instance.currentPosition.y / host.config.squareheight);

			if((ins_ceil_col == check_col || ins_flor_col == check_col) && (ins_ceil_row == check_row || ins_flor_row == check_row)) {
				instance.run();
				return true; //截获此事件 终止遍历
			} else {
				return false; //不截获此事件 使事件在全局监听器中继续遍历
			}
		}
	triggerToHandler.confirmTrigger = confirmEventHandler;

	//将要注册在全局事件监听器中的托管，目的是监听对于本活动的position事件
	var positionEventHandler = function(sender, params) {
			if(!instance.isEnable()) return false;
			//确定主角的位置是否与活动目前的位置相同
			var check_col = Math.round(sender.currentPosition.x / host.config.squarewidth);
			var check_row = Math.round(sender.currentPosition.y / host.config.squareheight);

			var ins_col = Math.round(instance.currentPosition.x / host.config.squarewidth);
			var ins_row = Math.round(instance.currentPosition.y / host.config.squareheight);

			if(ins_col == check_col && ins_row == check_row) {
				instance.run();
				return true; //截获此事件 终止遍历
			} else {
				return false; //不截获此事件 使事件在全局监听器中继续遍历
			}
		}
	triggerToHandler.positionTrigger = positionEventHandler;

	//将要注册在全局事件监听器中的托管，目的是监听对于本活动的frame/load事件
	var unconditionalEventHandler = function(sender, params) {
			if(!instance.isEnable()) return false;
			instance.run();
			return false; //不截获
		}
	triggerToHandler.frameTrigger = unconditionalEventHandler;
	triggerToHandler.loadTrigger = unconditionalEventHandler;

	this.load = function(handler) {
		//角色初始位置（以方格记）
		this.position = {
			x: Number(this.resourceNode.getElementsByTagName("position")[0].getElementsByTagName("x")[0].childNodes[0].nodeValue),
			y: Number(this.resourceNode.getElementsByTagName("position")[0].getElementsByTagName("y")[0].childNodes[0].nodeValue)
		}
		//记录角色上一次逗留的方格的位置
		this.lastPosition = {
			x: this.position.x * host.config.squarewidth,
			y: this.position.y * host.config.squarewidth
		}
		//记录角色的实时位置
		this.currentPosition = {
			x: this.position.x * host.config.squarewidth,
			y: this.position.y * host.config.squarewidth
		}
		//角色距上一次逗留的方格的距离
		this.distanceFromLastSquare = 0;
		this.speed = Number(this.resourceNode.getElementsByTagName("speed")[0].childNodes[0].nodeValue);
		this.actor = null;
		if(this.resourceNode.getElementsByTagName("bild").length > 0) {
			var actorid = this.resourceNode.getElementsByTagName("bild")[0].childNodes[0].nodeValue;
			this.actor = OS_Resource.resource.get(actorid);
		}
		this.direction = Number(this.resourceNode.getElementsByTagName("direction")[0].childNodes[0].nodeValue);
		this.mode = this.resourceNode.getElementsByTagName("mode")[0].childNodes[0].nodeValue;
		if(this.mode == "auto") {
			this.scope = {
				colspan: Number(this.resourceNode.getElementsByTagName("scope")[0].getElementsByTagName("colspan")[0].childNodes[0].nodeValue),
				rowspan: Number(this.resourceNode.getElementsByTagName("scope")[0].getElementsByTagName("rowspan")[0].childNodes[0].nodeValue)
			}
		}
		this.coverable = eval("(" + this.resourceNode.getElementsByTagName("coverable")[0].childNodes[0].nodeValue + ")");

		//加载可见条件
		for(var i = 0; i < this.resourceNode.childNodes.length; i++) {
			if(this.resourceNode.childNodes[i].nodeType != 1) continue;
			if(this.resourceNode.childNodes[i].nodeName == "condition") var conditionNode = this.resourceNode.childNodes[i];
		}

		if( !! conditionNode) {
			for(var i = 0; i < conditionNode.childNodes.length; i++) {
				if(conditionNode.childNodes[i].nodeType != 1) continue;
				enableCondition = OS_Condition.getInstance(host, this, conditionNode.childNodes[i]);
				enable = enableCondition.check();
				break;
			}
		}

		//地图位置占用
		this.occupy();

		//初始化脚本执行器
		var logic = this.resourceNode.getElementsByTagName("logic")[0];
		if( !! logic) {
			//初始化触发器
			var triggerGroup = logic.getElementsByTagName("triggerGroup")[0];
			for(var i = 0; i < triggerGroup.childNodes.length; i++) {
				if(triggerGroup.childNodes[i].nodeType != 1) {
					continue;
				}
				var trigger = triggerGroup.childNodes[i];
				var triggerName = trigger.nodeName;
				host.status[triggerName].register(triggerToHandler[triggerName]);
			}

			//初始化脚本队列
			actuators = [];
			var actuatorGroupNode = logic.getElementsByTagName("actuatorGroup")[0];
			var actuatorLoader = OS_Actuator.getInstance(actuatorGroupNode.nodeName);
			actuatorLoader.init(host, this, actuatorGroupNode, actuators);

		}
		this.loaded = true;
		handler(this);
	}

	this.update = function() {
		enable = true;
		if( !! enableCondition && !enableCondition.check()) {
			this.deoccupy();
			enable = false;
		} else if(!this.coverable) this.occupy();
		if(!enable) return;
		while( !! running && !paused) {
			if(actuatorPoint < actuators.length) {
				var func = actuators[actuatorPoint++];
				func();
			} else {
				this.stop();
			}
		}
	}

	this.faceto = function(d) {
		this.direction = d;
	}

	this.deoccupy = function() {
		if(this.coverable) return;
		if(!enable) return;
		var map = host.status.activeInterface.world.mapdata;
		var position_x = Math.round(this.currentPosition.x);
		var position_y = Math.round(this.currentPosition.y);
		map[Math.floor(position_y / host.config.squareheight)]
		[Math.floor(position_x / host.config.squarewidth)].occupied = false;
		map[Math.ceil(position_y / host.config.squareheight)]
		[Math.floor(position_x / host.config.squarewidth)].occupied = false;
		map[Math.floor(position_y / host.config.squareheight)]
		[Math.ceil(position_x / host.config.squarewidth)].occupied = false;
		map[Math.ceil(position_y / host.config.squareheight)]
		[Math.ceil(position_x / host.config.squarewidth)].occupied = false;
	}

	this.occupy = function() {
		if(this.coverable) return;
		if(!enable) return;
		var map = host.status.activeInterface.world.mapdata;
		var position_x = Math.round(this.currentPosition.x);
		var position_y = Math.round(this.currentPosition.y);
		map[Math.floor(position_y / host.config.squareheight)]
		[Math.floor(position_x / host.config.squarewidth)].occupied = true;
		map[Math.ceil(position_y / host.config.squareheight)]
		[Math.floor(position_x / host.config.squarewidth)].occupied = true;
		map[Math.floor(position_y / host.config.squareheight)]
		[Math.ceil(position_x / host.config.squarewidth)].occupied = true;
		map[Math.ceil(position_y / host.config.squareheight)]
		[Math.ceil(position_x / host.config.squarewidth)].occupied = true;
	}

	this.forward = function(dis, handlerkey, handler) {
		if( !! handler) moveHandler[handlerkey] = handler;
		this.deoccupy();
		var tempPosition = {
			x: this.currentPosition.x,
			y: this.currentPosition.y
		};
		var steplength = this.speed * host.delayTime / 1000;
		var distance = dis == undefined ? steplength : dis;
		switch(this.direction) {
		case 0:
			this.currentPosition.y -= distance;
			break;
		case 1:
			this.currentPosition.x += distance;
			break;
		case 2:
			this.currentPosition.y += distance;
			break;
		case 3:
			this.currentPosition.x -= distance;
			break;
		}
		if(!host.status.activeInterface.world.checkActivePosition(this)) {
			this.currentPosition = tempPosition;
			distance = 0;
		}
		this.distanceFromLastSquare += distance;
		this.occupy();
	}

	this.back = function(dis, handlerkey, handler) {
		if( !! handler) moveHandler[handlerkey] = handler;
		this.deoccupy();
		var tempPosition = {
			x: this.currentPosition.x,
			y: this.currentPosition.y
		};
		var steplength = this.speed * host.delayTime / 1000;
		var distance = dis == undefined ? steplength : dis;
		switch(this.direction) {
		case 0:
			this.currentPosition.y += distance;
			break;
		case 1:
			this.currentPosition.x -= distance;
			break;
		case 2:
			this.currentPosition.y -= distance;
			break;
		case 3:
			this.currentPosition.x += distance;
			break;
		}
		if(!host.status.activeInterface.world.checkActivePosition(this)) {
			this.currentPosition = tempPosition;
			distance = 0;
		}
		this.distanceFromLastSquare -= distance;
		this.occupy();
	}

	this.isInPosition = function() {
		if(this.distanceFromLastSquare == 0) {
			for(var index in moveHandler) {
				var func = moveHandler[index];
				func();
			}
			moveHandler = {};
			return true;
		}
		var limit = 0;
		if(this.direction == 1 || this.direction == 3) {
			limit = host.config.squarewidth;
		} else {
			limit = host.config.squareheight;
		}
		var steplength = this.speed * host.delayTime / 1000;
		if(this.distanceFromLastSquare > 0 && limit - this.distanceFromLastSquare < steplength) {
			this.forward(limit - this.distanceFromLastSquare);
			this.distanceFromLastSquare = 0;
			this.currentPosition.x = Math.round(this.currentPosition.x);
			this.currentPosition.y = Math.round(this.currentPosition.y);
			this.lastPosition.x = this.currentPosition.x;
			this.lastPosition.y = this.currentPosition.y;
			for(var index in moveHandler) {
				var func = moveHandler[index];
				func();
			}
			moveHandler = {};
			return true;
		}
		if(this.distanceFromLastSquare < 0 && this.distanceFromLastSquare + limit < steplength) {
			this.back(this.distanceFromLastSquare + limit);
			this.distanceFromLastSquare = 0;
			this.currentPosition.x = Math.round(this.currentPosition.x);
			this.currentPosition.y = Math.round(this.currentPosition.y);
			this.lastPosition.x = this.currentPosition.x;
			this.lastPosition.y = this.currentPosition.y;
			for(var index in moveHandler) {
				var func = moveHandler[index];
				func();
			}
			moveHandler = {};
			return true;
		}
		return false;
	}

	this.drawSelf = function() {
		if(!enable) return;
		if(!this.actor) return;
		var directions = ["up", "right", "down", "left"];
		var steps = [2, 1, 2, 3];
		var offset = this.currentPosition.x % (host.config.squarewidth * 2) + this.currentPosition.y % (host.config.squarewidth * 2);
		offset = Math.floor((offset + 8) % (host.config.squarewidth * 2) / 16);
		var index = directions[this.direction] + steps[offset];
		var currentFrame = this.actor.actions[index];
		host.stage.draw(currentFrame, this.currentPosition.x, this.currentPosition.y);
	}
};

OS_Resource.Builder.put("active", OS_Active);